package com.example.blockchain.service.impl;

import com.example.blockchain.entity.TradeObject;
import com.example.blockchain.entity.block.Block;
import com.example.blockchain.entity.block.BlockDownLoad;
import com.example.blockchain.entity.block.ContractObj;
import com.example.blockchain.utils.DataUtils;
import com.example.blockchain.utils.DateUtils;
import com.example.blockchain.utils.SQLManager;
import com.example.blockchain.utils.SQLiteHelper;
import com.example.blockchain.utils.encrypt.EthUtils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.web3j.crypto.Sign;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
public class BlockServiceImpl {


    @Resource
    private RestTemplate restTemplate;

    @Value("${node.ip}")
    private String ip;


    public void toChain(TradeObject tradeObject){
        String url = "http://" + ip + ":8001/data/trade";
        restTemplate.postForObject(url, tradeObject, String.class);
    }





    public static void checkBlockTable(String blockIndex) {
        Connection connection = null;
        try {
            String tableIndex = DataUtils.getBlockSerial(blockIndex);
            String sql0 = SQLManager.getBlockSql(tableIndex);
            connection = SQLiteHelper.getConnection();
            connection.setAutoCommit(false);
            Statement statement0 = connection.createStatement();
            statement0.executeUpdate(sql0);
            connection.commit();
        } catch (SQLException | ClassNotFoundException e) {
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e.getMessage();
            }
            e.getMessage();
        } finally {
            SQLiteHelper.close(connection);
        }
    }



    public static boolean save(Block block) {
        Connection connection = null;
        try {
            String tableIndex = DataUtils.getBlockSerial(block.getBlockIndex());
            connection = SQLiteHelper.getConnection();
            connection.setAutoCommit(false);
            String sql = "insert into [block" + tableIndex + "]([blockIndex],[preBlockHash],[path],[createTime],[blockHash],[randomNumber],[onMingChain]) values(?,?,?,?,?,?,?);";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setString(1, block.getBlockIndex() + "");
            statement.setString(2, block.getPreBlockHash());
            statement.setString(3, block.getPath());
            statement.setString(4, block.getCreateTime());
            statement.setString(5, block.getBlockHash());
            statement.setString(6, block.getRandomNumber());
            statement.setInt(7, 1);
            statement.execute();
            connection.commit();
            return true;
        } catch (Exception e) {
            if (connection != null) {
                try {
                    connection.rollback();
                } catch (SQLException e1) {
                    e.getMessage();
                }
            }
            e.getMessage();
        } finally {
            SQLiteHelper.close(connection);
        }
        return false;
    }


    /**
     * 保存区块文件信息
     *
     * @param bdl
     * @return
     */
    public static boolean saveBlockFile(BlockDownLoad bdl) {
        Block block = bdl.getBlock();
        return DataUtils.writeFile(DataUtils.getRelativePath(block.getPath()), bdl.getBlockFileStr());
    }


    /**
     * @param blockName
     * @return 查询表最后一条
     */
    public static Block queryLastBlock(String blockName) {
        Connection connection = null;
        try {
            connection = SQLiteHelper.getConnection();
            String sql = "select * from [" + blockName + "] order by id desc limit 0,1";
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            Block block = null;
            while (rs.next()) {
                block = new Block();
                block.setId(rs.getInt("ID"));
                block.setBlockIndex(rs.getString("blockIndex"));
                block.setCreateTime(rs.getString("createTime"));
                block.setBlockHash(rs.getString("blockHash"));
                block.setPreBlockHash(rs.getString("preBlockHash"));
                block.setPath(rs.getString("path"));
                block.setRandomNumber(rs.getString("randomNumber"));
                return block;
            }
        } catch (Exception e) {
            e.getMessage();
        } finally {
            SQLiteHelper.close(connection);
        }
        return null;
    }


    /**
     * @param blockName
     * @return 查询最后5条
     */
    public static List<Block> queryBlockData(String blockName) {
        Connection connection = null;
        try {
            List<Block> list = new ArrayList<>();
            connection = SQLiteHelper.getConnection();
            String sql = "select * from [" + blockName + "] order by id desc limit 0,5";
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            Block block = null;
            while (rs.next()) {
                block = new Block();
                block.setId(rs.getInt("ID"));
                block.setBlockIndex(rs.getString("blockIndex"));
                block.setCreateTime(rs.getString("createTime"));
                block.setBlockHash(rs.getString("blockHash"));
                block.setPreBlockHash(rs.getString("preBlockHash"));
                block.setPath(rs.getString("path"));
                block.setRandomNumber(rs.getString("randomNumber"));
                list.add(block);
            }
            return list;
        } catch (Exception e) {
            e.getMessage();
        } finally {
            SQLiteHelper.close(connection);
        }
        return null;
    }




    public static List<Block> queryBlockByBlockIndex(String blockIndex) {
        List<Block> list = new ArrayList<Block>();
        Connection connection = null;
        try {
            String tableIndex = DataUtils.getBlockSerial(blockIndex);
            connection = SQLiteHelper.getConnection();
            String sql = "select * from [block" + tableIndex + "] where blockIndex='" + blockIndex + "' order by blockIndex desc";
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            Block block = null;
            while (rs.next()) {
                block = new Block();
                block.setBlockIndex(rs.getString("blockIndex"));
                block.setCreateTime(rs.getString("createTime"));
                block.setBlockHash(rs.getString("blockHash"));
                block.setPreBlockHash(rs.getString("preBlockHash"));
                block.setPath(rs.getString("path"));
                block.setRandomNumber(rs.getString("randomNumber"));
                list.add(block);
            }
        } catch (Exception e) {
            e.getMessage();
        } finally {
            SQLiteHelper.close(connection);
        }
        return list;
    }



    public static Block getBlockObeject(ZipInputStream zis) {
        ByteArrayOutputStream bos = null;
        try {
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[512];
            int len = 0;
            while ((len = zis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            String blockStr = new String(bos.toByteArray());//get block object
            Block block = new Gson().fromJson(blockStr, Block.class);
            return block;
            //}
        } catch (JsonSyntaxException | IOException e) {
            e.getMessage();

        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.getMessage();

                }
            }
        }
        return null;
    }

    public static String getBlockFileStr(ZipInputStream zis) {
        ByteArrayOutputStream bos = null;
        try {
            //if(zis.getNextEntry() != null) {
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[512];
            int len = 0;
            while ((len = zis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            String blockfileStr = new String(bos.toByteArray());//get block file str
            return blockfileStr;
            //}
        } catch (JsonSyntaxException | IOException e) {
            e.getMessage();

        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.getMessage();

                }
            }
        }
        return "";
    }


    public static String getMaxBlockIndexStr(ZipInputStream zis) {
        ByteArrayOutputStream bos = null;
        try {
            //if(zis.getNextEntry() != null) {
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = zis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            String maxBlockIndex = new String(bos.toByteArray());//get block file str
            return maxBlockIndex;
            //}
        } catch (JsonSyntaxException | IOException e) {
            e.getMessage();

        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.getMessage();

                }
            }
        }
        return "";
    }


}
